home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / unixlib.lha / unix / src / signals.c < prev    next >
C/C++ Source or Header  |  1996-10-21  |  5KB  |  298 lines

  1. #include "amiga.h"
  2. #include "timers.h"
  3. #include "signals.h"
  4. #include "processes.h"
  5.  
  6. void __stdargs _CXFERR(int);
  7.  
  8. /* When one of these occur, call handle_signals */
  9. static ULONG signalsigs;
  10.  
  11. void (*_sig_handlers[NSIG]) (int);
  12.  
  13. long _sig_mask, _sig_pending;
  14.  
  15. /* These can be generated only by bsdsocket.library */
  16. long _sigio_sig = -1, _sigurg_sig = -1;
  17.  
  18. extern void _fail(char *format,...);
  19. extern void _message(char *format,...);
  20. extern int (*_break_func)(void);
  21.  
  22.  
  23. /* Alarm signal */
  24. /* ------------ */
  25.  
  26. static struct timeinfo *alarm_timer;
  27.  
  28. static int check_alarm(void)
  29. {
  30.     return alarm_timer && _timer_expired(alarm_timer);
  31. }
  32.  
  33. /*
  34.  *  Schedule a SIGALRM after secs seconds
  35.  */
  36. void alarm(int secs)
  37. {
  38.     _timer_start(alarm_timer, secs, 0);
  39. }
  40.  
  41. static void init_alarm(void)
  42. {
  43.     if (!(alarm_timer = _alloc_timer()))
  44.     _fail("Failed to create timer");
  45.     signalsigs |= _timer_sig(alarm_timer);
  46. }
  47.  
  48. static void cleanup_alarm(void)
  49. {
  50.     _free_timer(alarm_timer);
  51. }
  52.  
  53. /* SIGINT definition */
  54. /* ----------------- */
  55.  
  56. static void init_sigint(void)
  57. {
  58.     signalsigs |= SIGBREAKF_CTRL_C;
  59. }
  60.  
  61. /* static void cleanup_sigint(void) { } */
  62.  
  63. static int check_sigint(ULONG sigs)
  64. {
  65.     return (sigs & SIGBREAKF_CTRL_C) != 0;
  66. }
  67.  
  68. /* SIGQUIT definition */
  69. /* ------------------ */
  70.  
  71. static void init_sigquit(void)
  72. {
  73.     signalsigs |= SIGBREAKF_CTRL_D;
  74. }
  75.  
  76. /* static void cleanup_sigquit(void) { } */
  77.  
  78. static int check_sigquit(ULONG sigs)
  79. {
  80.     return (sigs & SIGBREAKF_CTRL_D) != 0;
  81. }
  82.  
  83. /* SIGCHLD definition */
  84. /* ------------------ */
  85.  
  86. static void init_children(void)
  87. {
  88.     _init_processes();
  89.     signalsigs |= 1L << _children_exit->mp_SigBit;
  90. }
  91.  
  92. static void cleanup_children(void)
  93. {
  94.     _cleanup_processes();
  95. }
  96.  
  97. static int check_children(void)
  98. {
  99.     struct exit_message *msg;
  100.     int change = FALSE;
  101.  
  102.     while (msg = (struct exit_message *) GetMsg(_children_exit)) {
  103.     struct process *p;
  104.  
  105.     if ((p = _find_pid(msg->pid)) && p->status == alive) {
  106.         change = TRUE;
  107.         p->status = exited;
  108.         p->rc = msg->rc;
  109.     }
  110.     FreeMem(msg, sizeof(struct exit_message));
  111.     }
  112.     return change;
  113. }
  114.  
  115. /* SIGIO definition */
  116. /* ---------------- */
  117.  
  118. static void init_sigio(void)
  119. {
  120.     if (_sigio_sig >= 0)
  121.     signalsigs |= sigmask(_sigio_sig);
  122. }
  123.  
  124. /* static void cleanup_sigio(void) { } */
  125.  
  126. static int check_sigio(ULONG sigs)
  127. {
  128.     return _sigio_sig < 0 ? 0 : (sigs & sigmask(_sigio_sig)) != 0;
  129. }
  130.  
  131. /* SIGURG definition */
  132. /* ----------------- */
  133.  
  134. static void init_sigurg(void)
  135. {
  136.     if (_sigurg_sig >= 0)
  137.     signalsigs |= sigmask(_sigurg_sig);
  138. }
  139.  
  140. /* static void cleanup_sigurg(void) { } */
  141.  
  142. static int check_sigurg(ULONG sigs)
  143. {
  144.     return _sigurg_sig < 0 ? 0 : (sigs & sigmask(_sigurg_sig)) != 0;
  145. }
  146.  
  147. /* Signal dispatching */
  148. /* ------------------ */
  149.  
  150. /*
  151.  *  Do the action associated with signal sig if it isn't masked
  152.  *  Mask it for the duration of the signal exec
  153.  */
  154. void _sig_dispatch(int sig)
  155. {
  156.     void (*fn) (int);
  157.     int smask = sigmask(sig);
  158.  
  159.     if (sig == SIGKILL)
  160.     __exit(0);
  161.  
  162.     if (_sig_mask & smask) {
  163.     _sig_pending |= smask;
  164.     } else {
  165.     do {
  166.         _sig_pending &= ~smask;
  167.         if (sig >= 0 && sig < NSIG) {
  168.         fn = _sig_handlers[sig];
  169.         /*
  170.          * Note: SIGINT is special because onbreak() may
  171.          * override the SIG_DFL and SIG_IGN settings.
  172.          */
  173.         if (sig == SIGINT) {
  174.             _sig_mask |= smask;
  175.             if (_break_func()) { 
  176.             _message("user interrupt");
  177.             __exit(0);
  178.             }
  179.             _sig_mask &= ~smask;
  180.         } else if (fn == SIG_DFL) {
  181.             switch (sig) {
  182.             case SIGURG:
  183.             case SIGCHLD:
  184.             case SIGIO:
  185.             case SIGWINCH:
  186.                 break;
  187.             case SIGQUIT:
  188.                 _message("user interrupt");
  189.             default:
  190.                 __exit(0);
  191.             }
  192.         } else if (fn != SIG_IGN) {
  193.             _sig_mask |= smask;
  194.             _sig_handlers[sig] (sig);
  195.             _sig_mask &= ~smask;
  196.         }
  197.         }
  198.     }
  199.     while (_sig_pending & smask);    /* Signal may have been generated during
  200.                        the signal handling function. */
  201.     }
  202. }
  203.  
  204. ULONG _check_signals(ULONG extra_sigs)
  205. {
  206.     return SetSignal(0, signalsigs | extra_sigs);
  207. }
  208.  
  209. ULONG _wait_signals(ULONG extra_sigs)
  210. {
  211.     return Wait(signalsigs | extra_sigs);
  212. }
  213.  
  214. int _handle_signals(ULONG sigs)
  215. {
  216.     int signaled = 0;
  217.  
  218.     if (check_alarm()) {
  219.     signaled = 1;
  220.     _sig_dispatch(SIGALRM);
  221.     }
  222.     if (check_sigint(sigs)) {
  223.     signaled = 1;
  224.     _sig_dispatch(SIGINT);
  225.     }
  226.     if (check_sigquit(sigs)) {
  227.     signaled = 1;
  228.     _sig_dispatch(SIGQUIT);
  229.     }
  230.     if (check_sigio(sigs)) {
  231.     signaled = 1;
  232.     _sig_dispatch(SIGIO);
  233.     }
  234.     if (check_sigurg(sigs)) {
  235.     signaled = 1;
  236.     _sig_dispatch(SIGURG);
  237.     }
  238.     if (check_children()) {
  239.     signaled = 1;
  240.     _sig_dispatch(SIGCHLD);
  241.     }
  242.     return signaled;
  243. }
  244.  
  245. /*
  246.  *  Patch into SAS signal stuff so as to replace it
  247.  */
  248. void __stdargs _CXFERR(int code)
  249. {
  250.     extern int _FPERR;
  251.  
  252.     _FPERR = code;
  253.     _sig_dispatch(SIGFPE);
  254. }
  255.  
  256. /*
  257.  *  Checks all signals
  258.  */
  259. void __regargs __chkabort(void)
  260. {
  261.     _handle_signals(_check_signals(0));
  262. }
  263.  
  264. void __stdargs Chk_Abort(void)
  265. {
  266.     __chkabort();
  267. }
  268.  
  269. /* Initialisation */
  270. /* -------------- */
  271.  
  272. void _init_signals(void)
  273. {
  274.     int i;
  275.  
  276.     for (i = 0; i < NSIG; i++)
  277.     _sig_handlers[i] = SIG_DFL;
  278.     _sig_mask = _sig_pending = 0;
  279.     signalsigs = 0;
  280.  
  281.     init_sigint();
  282.     init_sigquit();
  283.     init_sigio();
  284.     init_sigurg();
  285.     init_alarm();
  286.     init_children();
  287. }
  288.  
  289. void _cleanup_signals(void)
  290. {
  291.     cleanup_alarm();
  292.     /* cleanup_sigquit(); */
  293.     /* cleanup_sigint(); */
  294.     /* cleanup_sigio(); */
  295.     /* cleanup_sigurg(); */
  296.     cleanup_children();
  297. }
  298.